package cn.stronglink.suite.core.log.aspect;

import java.lang.reflect.Method;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.toolkit.IdWorker;

import cn.stronglink.asset.model.SysOperateLog;
import cn.stronglink.asset.model.User;
import cn.stronglink.asset.module.sys.log.service.SysLogService;
import cn.stronglink.asset.module.sys.user.service.UserService;
import cn.stronglink.suite.core.log.annotation.OperateLog;
import cn.stronglink.suite.core.log.annotation.OperateLog.OpType;
import cn.stronglink.suite.core.util.WebUtil;


@Aspect
@Component
public class OperateLogAspect {

	@Autowired
	private SysLogService sysLogService;
	@Autowired
	private UserService userService;
	private static final Logger logger = LoggerFactory.getLogger(OperateLogAspect.class);
	

	@Before("@annotation(cn.stronglink.suite.core.log.annotation.OperateLog)")
	public void doBefore(JoinPoint joinPoint) {
//		System.out.println("=====SysLogAspectǰ��֪ͨ��ʼ=====");
		handleLog(joinPoint, null);
	}

	@AfterReturning("@annotation(cn.stronglink.suite.core.log.annotation.OperateLog)")
	public void doAfter(JoinPoint joinPoint) {
//		System.out.println("=====SysLogAspect����֪ͨ��ʼ=====");
	}

	@AfterThrowing(value = "@annotation(cn.stronglink.suite.core.log.annotation.OperateLog)", throwing = "e")
	public void doAfter(JoinPoint joinPoint, Exception e) {
//		System.out.println("=====SysLogAspect�쳣֪ͨ��ʼ=====");
		handleLog(joinPoint, e);
	}

	private void handleLog(JoinPoint joinPoint, Exception e) {
		try {
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
			// 获得注解
			OperateLog logger = giveController(joinPoint);
			if (logger == null) {
				return;
			}
			String signature = joinPoint.getSignature().toString(); // ��ȡĿ�귽��ǩ��
			String methodName = signature.substring(signature.lastIndexOf(".") + 1, signature.indexOf("("));

			String longTemp = joinPoint.getStaticPart().toLongString();
			String classType = joinPoint.getTarget().getClass().getName();

			Class<?> clazz = Class.forName(classType);

			Method[] methods = clazz.getDeclaredMethods();

			for (Method method : methods) {

				if (method.isAnnotationPresent(OperateLog.class) && method.getName().equals(methodName)) {
					Long userId=WebUtil.getCurrentUser();
					if(userId==null){
						return;
					}
					String username = "",actName="";
					User user = userService.qryUserById(userId);
					actName=user.getName();
					username=user.getAccount();
					OpType type = logger.type();
					if("SEARCH".equals(type.toString())){
						return;
					}
					String module = logger.module();
					String desc = logger.desc();
					SysOperateLog log=new SysOperateLog();
					log.setId(IdWorker.getId());
					log.setArgs(optionContent(joinPoint.getArgs(), methodName));
					log.setActName(actName);
					log.setUserName(username);
					log.setModule(module);
					log.setOperateTime(new Date());
					log.setOperateType(type.toString());
					log.setDescription(desc);
					log.setIp(WebUtil.getHost(request));
					log.setActName(actName);
					sysLogService.insertOperateLog(log);
					
				}
			}
		} catch (Exception exp) {
			logger.error("�쳣��Ϣ:{}", exp.getMessage());
			exp.printStackTrace();
		}
	}

	private static OperateLog giveController(JoinPoint joinPoint) throws Exception {
		Signature signature = joinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = methodSignature.getMethod();

		if (method != null) {
			return method.getAnnotation(OperateLog.class);
		}
		return null;
	}

	/**
	 * 使用Java反射来获取被拦截方法(insert、update)的参数值， 将参数值拼接为操作内容
	 */
	public String optionContent(Object[] args, String mName) throws Exception {
		//System.out.println(JSON.toJSON(args));
		if (args == null) {
			return null;
		}
		StringBuffer rs = new StringBuffer();
		rs.append(mName);
		String className = null;
		int index = 1;
		for (Object info : args) {			
			// ��ȡ��������
			className = info.getClass().getName();
			className = className.substring(className.lastIndexOf(".") + 1);
			if ("ShiroHttpServletRequest".equals(className) || "ShiroHttpServletResponse".equals(className)
					|| "BindingAwareModelMap".equals(className) || "RequestFacade".equals(className) 
					|| "ResponseFacade".equals(className)||"CookieHttpSessionStrategy$MultiSessionHttpServletResponse".equals(className)) {
				continue;
			}
			String arg = JSON.toJSONString(info);
			rs.append("[参数" + index + "，值：" + arg);
			
			rs.append("]");
			index++;
		}
		return rs.toString();
	}
}
